/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.geotools.geosearch;

import java.io.IOException;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geotools.data.DataUtilities;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureCollections;
import org.geotools.feature.collection.AbstractFeatureVisitor;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.geometry.DirectPosition2D;
import org.geotools.graph.structure.Edge;
import org.geotools.map.MapLayer;
import org.geotools.util.NullProgressListener;
import org.is.city.routemanager.Layers.PointsLayer;
import org.is.city.routemanager.Layers.RouteLayer;
import org.opengis.feature.Feature;
import org.opengis.feature.simple.SimpleFeature;

/**
 *
 * @author oleg
 */
public class Route {

    String id;
    RouteLayer routeLayer;
    PointsLayer pointsLayer;
    MapLayer route;
    MapLayer points;
    String routeTitle;
    AbstractRouteFactory routeFactory;
    public boolean updated = false;
    LinkedList<RoutePoint> routePointsList;
    boolean text_mark=false;

    /*
     * 
     */
    public Route(MapLayer route, MapLayer points) {
        this.id = UUID.randomUUID().toString();
        this.route = route;
        this.points = points;
        routeLayer = (RouteLayer) route.toLayer();
        pointsLayer = (PointsLayer) points.toLayer();
        routeTitle = routeLayer.getTitle();
        
    }

    private void init(){
        setLength();
        initRouteList();
        setRouteTitle(getRouteLayer().getTitle()+ " " + Math.round(this.getLength()));
    }

    /**
     * Заполняет список routePointsList значениями по точечному слою
     */
    private void initRouteList() {
        try {
            routePointsList = new LinkedList<RoutePoint>();
            FeatureCollection features = this.getPointsLayer().getFeatureSource().getFeatures();
            Object[] featuresarray = features.toArray();
            int i = 0;
            for (i = featuresarray.length - 1; i >= 0; i--) {
                SimpleFeature feature = (SimpleFeature) featuresarray[i];
                RoutePoint routePoint = new RoutePoint(feature);
                //routePoint.setName("Точка №" + Integer.toString(i));
                routePointsList.add(routePoint);
            }
            
        } catch (IOException ex) {
            Logger.getLogger(Route.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public Route(RouteLayer routeLayer, PointsLayer pointsLayer) {
        this.id = UUID.randomUUID().toString();
        this.routeLayer = routeLayer;
        this.pointsLayer = pointsLayer;
        try {
            int size = pointsLayer.getSimpleFeatureSource().getFeatures().size();
            System.out.println("sdas");
        } catch (IOException ex) {
            Logger.getLogger(Route.class.getName()).log(Level.SEVERE, null, ex);
        }
        init();
        try {
            int size = pointsLayer.getSimpleFeatureSource().getFeatures().size();
            System.out.println("sdas");
        } catch (IOException ex) {
            Logger.getLogger(Route.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public Route() {
        RouteLayer routeLayer1 = new RouteLayer(null, null);
        PointsLayer pointsLayer1 = new PointsLayer(null, null);
        setRouteLayer(routeLayer1);
        setPointsLayer(pointsLayer1);
    }

    Route(RouteLayer routeLayer, PointsLayer pointsLayer, AbstractRouteFactory routeFactory) {
        this.id = UUID.randomUUID().toString();
        this.routeLayer = routeLayer;
        this.pointsLayer = pointsLayer;
        this.routeFactory = routeFactory;
        try {
            int size = pointsLayer.getSimpleFeatureSource().getFeatures().size();
            System.out.println("sdas");
        } catch (IOException ex) {
            Logger.getLogger(Route.class.getName()).log(Level.SEVERE, null, ex);
        }
        setLength();
        init();
        try {
            int size = pointsLayer.getSimpleFeatureSource().getFeatures().size();
            System.out.println("sdas");
        } catch (IOException ex) {
            Logger.getLogger(Route.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public PointsLayer getPointsLayer() {
        return pointsLayer;
    }

    public void setPointsLayer(PointsLayer pointsLayer) {
        this.pointsLayer = pointsLayer;
    }

    public RouteLayer getRouteLayer() {
        return routeLayer;
    }

    public void setRouteLayer(RouteLayer routeLayer) {
        this.routeLayer = routeLayer;
    }

    public String getRouteTitle() {
        return routeTitle;
    }

    public void setRouteTitle(String routeTitle) {
        this.routeTitle = routeTitle;
    }

    public double getLength() {
        return length;
    }
    double length;

    private void setLength() {
        length = 0;
        try {
            routeLayer.getFeatureSource().getFeatures().accepts(new AbstractFeatureVisitor() {

                @Override
                public void visit(Feature feature) {
                    length += (Double) feature.getProperty("LENGTH").getValue();
                }
            }, new NullProgressListener());

        } catch (IOException ex) {
            Logger.getLogger(Route.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public DirectPosition2D[] getPointsPositions() {
        /*
        try {
        //PointsLayer pointsLayer = getPointsLayer();
        SimpleFeatureSource simple = DataUtilities.simple(pointsLayer.getFeatureSource());
        SimpleFeatureCollection features = simple.getFeatures();
        SimpleFeatureIterator features1 = features.features();
        DirectPosition2D result[] = new DirectPosition2D[features.size()];
        int i = 0;
        while (features1.hasNext()) {
        SimpleFeature next = features1.next();
        Point point = (Point) next.getDefaultGeometry();
        result[i] = new DirectPosition2D(point.getX(), point.getY());
        i++;
        }
        features1.close();
        return result;
        } catch (IOException ex) {
        Logger.getLogger(Route.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
         */
        DirectPosition2D result[] = new DirectPosition2D[routePointsList.size()];
        Iterator<RoutePoint> iterator = routePointsList.iterator();
        int i=0;
        while(iterator.hasNext()){
            RoutePoint routePoint = iterator.next();
            result[i] = routePoint.getCoordinate();
            i++;
        }
        return result;
    }

    public String getId() {
        return id;
    }

    public void reorderPoints(LinkedList<RoutePoint> points) {
        Route createRoute = routeFactory.createRoute(points, AbstractRouteFactory.OrderType.DONTORDER);
        this.routeLayer = createRoute.getRouteLayer();
        this.pointsLayer = createRoute.getPointsLayer();
        setLength();
        //init();
        routePointsList = points;
    }

    public void buildFromRoutePoints(LinkedList<RoutePoint> list ){
        Route createRoute = routeFactory.createRoute(list, AbstractRouteFactory.OrderType.DONTORDER);
        this.routeLayer = createRoute.getRouteLayer();
        this.pointsLayer = createRoute.getPointsLayer();
        setLength();
        init();
    }
    
    public void removePoint(DirectPosition2D point) {
        LinkedList<RoutePoint> newList=new LinkedList<RoutePoint>();
        for(Iterator<RoutePoint> iterator = routePointsList.iterator() ; iterator.hasNext();){
            RoutePoint p = iterator.next();
            if(!p.getCoordinate().equals(point)){
                newList.add(p);
            }
        }
        routePointsList=newList;
        buildFromRoutePoints(routePointsList);
    }

    public void removePoint(RoutePoint point) {
        LinkedList<RoutePoint> newList=new LinkedList<RoutePoint>();
        for(Iterator<RoutePoint> iterator = routePointsList.iterator() ; iterator.hasNext();){
            RoutePoint p = iterator.next();
            if(!p.getCoordinate().equals(point.getCoordinate())){
                newList.add(p);
            }
        }
        routePointsList=newList;
        buildFromRoutePoints(routePointsList);
    }

    public LinkedList<RoutePoint> getRoutePointsList() {
        return routePointsList;
    }

    public boolean setTextMark(boolean text_mark){
        this.text_mark = text_mark;
        try {
            int size = pointsLayer.getSimpleFeatureSource().getFeatures().size();
            if(size==0)
                return text_mark;
            System.out.println("sdas");
        } catch (IOException ex) {
            Logger.getLogger(Route.class.getName()).log(Level.SEVERE, null, ex);
        }
        PointsLayer pointsLayer1 = this.getPointsLayer();
        if(pointsLayer1==null)
            return false;
        MyStyle ms = new MyStyle(MyStyle.GeomType.POINT);
        try {
            pointsLayer1.setStyle(ms.createPointRouteStyle(pointsLayer1.getFeatureSource().getSchema().getGeometryDescriptor(), DataUtilities.simple(pointsLayer.getFeatureSource()).getFeatures(), text_mark));
        } catch (IOException ex) {
            Logger.getLogger(Route.class.getName()).log(Level.SEVERE, null, ex);
        }
        return text_mark;
    }

    public boolean getTextMark(){
        return text_mark;
    }

    
    public void dataChanged(){
        routeLayer.dataChanged();
        pointsLayer.dataChanged();
    }

}
